//
// asm.h
// some assembler macros
//
// (c) 2008 why the lucky stiff, the freelance professor
//

//
// PNAsm(vt = PN_TUSER, siz, ptr, len)
//   -> PNFlex(vt = PN_TUSER, siz, ...)
// overhead of 6 words on x86, but don't have to
// do constant forwarding tricks.
//
#ifndef POTION_ASM_H
#define POTION_ASM_H

#include <stddef.h>

// PNAsm 存储块长度、扩容单位
#define ASM_UNIT 512

// .from: 原来是 size_t -> PN_SIZE
typedef struct {
  PN_SIZE from;
  PN_SIZE to;
} PNJumps;

// 构造特定平台的 PNTarget 结构对象
#define MAKE_TARGET(arch) PNTarget potion_target = { \
    .setup = potion_target_setup, \
    .stack = potion_target_stack, \
    .registers = potion_target_registers, \
    .local = potion_target_local, \
    .upvals = potion_target_upvals, \
    .jmpedit = potion_target_jmpedit, \
    .op = { \
      (OP_F)NULL, \
      (OP_F)potion_target_op_move, \
      (OP_F)potion_target_op_loadval, \
      (OP_F)potion_target_op_loadpn, \
      (OP_F)potion_target_op_self, \
      (OP_F)potion_target_op_newtuple, \
      (OP_F)potion_target_op_settuple, \
      (OP_F)potion_target_op_getlocal, \
      (OP_F)potion_target_op_setlocal, \
      (OP_F)potion_target_op_getupval, \
      (OP_F)potion_target_op_setupval, \
      (OP_F)NULL, \
      (OP_F)potion_target_op_settable, \
      (OP_F)potion_target_op_newlick, \
      (OP_F)potion_target_op_getpath, \
      (OP_F)potion_target_op_setpath, \
      (OP_F)potion_target_op_add, \
      (OP_F)potion_target_op_sub, \
      (OP_F)potion_target_op_mult, \
      (OP_F)potion_target_op_div, \
      (OP_F)potion_target_op_rem, \
      (OP_F)potion_target_op_pow, \
      (OP_F)potion_target_op_not, \
      (OP_F)potion_target_op_cmp, \
      (OP_F)potion_target_op_eq, \
      (OP_F)potion_target_op_neq, \
      (OP_F)potion_target_op_lt, \
      (OP_F)potion_target_op_lte, \
      (OP_F)potion_target_op_gt, \
      (OP_F)potion_target_op_gte, \
      (OP_F)potion_target_op_bitn, \
      (OP_F)potion_target_op_bitl, \
      (OP_F)potion_target_op_bitr, \
      (OP_F)potion_target_op_pipe, \
      (OP_F)potion_target_op_caret, \
      (OP_F)potion_target_op_amp, \
      (OP_F)potion_target_op_def, \
      (OP_F)potion_target_op_bind, \
      (OP_F)potion_target_op_message, \
      (OP_F)potion_target_op_jmp, \
      (OP_F)potion_target_op_test, \
      (OP_F)potion_target_op_testjmp, \
      (OP_F)potion_target_op_notjmp, \
      (OP_F)potion_target_op_named, \
      (OP_F)potion_target_op_call, \
      (OP_F)potion_target_op_callset, \
      (OP_F)NULL, \
      (OP_F)potion_target_op_return, \
      (OP_F)potion_target_op_proto, \
      (OP_F)potion_target_op_class \
    }, \
    .finish = potion_target_finish, \
    .mcache = potion_target_mcache, \
    .ivars = potion_target_ivars \
  }

// 写入汇编指令：单字节
// 注意，因为可能重新分配内存，所以需要更新。
// #define ASM(ins) *asmp = potion_asm_put(P, *asmp, (PN)(ins), sizeof(u8))
// 写入汇编指令：双字节
// 未使用（以及 put 函数内）
// #define ASM2(pn) *asmp = potion_asm_put(P, *asmp, (PN)(pn), 2)
// 写入汇编指令：四字节（64位）
// #define ASMI(pn) *asmp = potion_asm_put(P, *asmp, (PN)(pn), sizeof(int))
// 写入汇编指令：八字节（64位）
// #define ASMN(pn) *asmp = potion_asm_put(P, *asmp, (PN)(pn), sizeof(PN))

PNAsm *potion_asm_new  (Potion *P);
PNAsm *potion_asm_clear(Potion *P, PNAsm * volatile asmb);
PNAsm *potion_asm_put  (Potion *P, PNAsm * volatile asmb, PN val, size_t len);
PNAsm *potion_asm_op   (Potion *P, PNAsm * volatile asmb, int ins, int _a, int _b);
PNAsm *potion_asm_write(Potion *P, PNAsm * volatile asmb, char *str, size_t len);

#endif
